# Root CMake File of Dragon Script
# Copyright (C) 2009 Hajime Yoshimori <RoarLudros@gmail.com>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

cmake_minimum_required(VERSION 2.6)

PROJECT(DragonScript C CXX)	# C is needed by gettext.
set(PROJECT_MAJOR_VERSION   "0")
set(PROJECT_MINOR_VERSION   "0")
set(PROJECT_RELEASE_VERSION "1")
set(PROJECT_STABLE_VERSION  "${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_RELEASE_VERSION}")

# CMAKE_RUNTIME_PATH ... The path for runtimes directory
if(NOT CMAKE_RUNTIME_PATH)
  set(CMAKE_RUNTIME_PATH "bin")
endif(NOT CMAKE_RUNTIME_PATH)

# CMAKE_LIBRARY_PATH ... The path for libraries directory
if(NOT CMAKE_LIBRARY_PATH)
  set(CMAKE_LIBRARY_PATH "lib")
endif(NOT CMAKE_LIBRARY_PATH)

# CMAKE_INCLUDE_PATH ... The path for include files directory
if(NOT CMAKE_INCLUDE_PATH)
  set(CMAKE_INCLUDE_PATH "include")
endif(NOT CMAKE_INCLUDE_PATH)

# CMAKE_DATA_PATH ... The path for other files directory
if(NOT CMAKE_DATA_PATH)
  set(CMAKE_DATA_PATH "share")
endif(NOT CMAKE_DATA_PATH)

# CMAKE_DOC_PATH ... The path for document files directory
if(NOT CMAKE_DOC_PATH)
  set(CMAKE_DOC_PATH "${CMAKE_DATA_PATH}/doc/DragonScript")
endif(NOT CMAKE_DOC_PATH)

if(NOT DRAGON_DATA_PATH)
  set(DRAGON_DATA_PATH "${CMAKE_DATA_PATH}/DragonScript")
endif(NOT DRAGON_DATA_PATH)

# MO_INSTALL_PATH ... The i18n file directory.
if(NOT MO_INSTALL_PATH)
  set(MO_INSTALL_PATH "${DRAGON_DATA_PATH}/locale")
endif(NOT MO_INSTALL_PATH)

# MO_INSTALL_PATH_FOR_SUB ... The i18n file directory for sub files.
# These are commands, not messages.
if(NOT MO_INSTALL_PATH_FOR_SUB)
  set(MO_INSTALL_PATH_FOR_SUB "${DRAGON_DATA_PATH}/locale")
endif(NOT MO_INSTALL_PATH_FOR_SUB)

# LIBDRAGONSCRIPT_DOMAIN_NAME ... domain name for libdragonscript.
if(NOT LIBDRAGONSCRIPT_DOMAIN_NAME)
  set(LIBDRAGONSCRIPT_DOMAIN_NAME "libdragonscript")
endif(NOT LIBDRAGONSCRIPT_DOMAIN_NAME)


# CMAKE_MODULE_APPS_PATH ... Additional Cmake Path.
if(NOT CMAKE_MODULE_APPS_PATH)
  set(CMAKE_MODULE_APPS_PATH "/apps/cmake/modules")
endif(NOT CMAKE_MODULE_APPS_PATH)

# CMAKE_MODULE_PATH ... The path for installed cmake modules
set(CMAKE_MODULE_PATH  ${CMAKE_MODULE_PATH}
					  "${CMAKE_ROOT}/Modules"
					  "${CMAKE_ROOT}/../${CMAKE_MODULE_APPS_PATH}")

# CDRAGON_DOMAIN_NAME ... domain name for cdragon.
if(NOT CDRAGON_DOMAIN_NAME)
  set(CDRAGON_DOMAIN_NAME "cdragon")
endif(NOT CDRAGON_DOMAIN_NAME)

# GDRAGON_DOMAIN_NAME ... domain name for gdragon.
if(NOT GDRAGON_DOMAIN_NAME)
  set(GDRAGON_DOMAIN_NAME "gdragon")
endif(NOT GDRAGON_DOMAIN_NAME)

# KDRAGON_DOMAIN_NAME ... domain name for kdragon.
if(NOT KDRAGON_DOMAIN_NAME)
  set(KDRAGON_DOMAIN_NAME "kdragon")
endif(NOT KDRAGON_DOMAIN_NAME)

# MAKE_DOC ... whether make document.
if(NOT MAKE_DOC)
  set(MAKE_DOC 0)
endif(NOT MAKE_DOC)

# uninstall target
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
               "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
               IMMEDIATE @ONLY)
add_custom_target(uninstall
                  "${CMAKE_COMMAND}" -P 
                  "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")

include_directories("${CMAKE_CURRENT_BINARY_DIR}")

# external packages.
find_package(GTK)
find_package(Libintl)
find_package(Gettext REQUIRED)
find_package(Curses)
if(NOT WIN32)
  find_package(KDE4)
endif(NOT WIN32)

set(LIBS ${LIBS} ${LIBINTL_LIBRARIES})

find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)

set(GETTEXT_EXTRACT     "${CMAKE_CURRENT_SOURCE_DIR}/DSGettextExtract.cmake")
set(GETTEXT_INITORMERGE "${CMAKE_CURRENT_SOURCE_DIR}/DSGettextInitOrMerge.cmake")
include("${CMAKE_CURRENT_SOURCE_DIR}/DSInternationalizationMacros.cmake")

IF(CMAKE_COMPILER_IS_GNUCC)
  SET(CMAKE_C_FLAGS 
	"${CMAKE_C_FLAGS} -D_ISOC99_SOURCE -D_ISOC9X_SOURCE-fmessage-length=0")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
IF(CMAKE_COMPILER_IS_GNUCXX)
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -D_ISOC99_SOURCE -D_ISOC9X_SOURCE")
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmessage-length=0 -fexceptions -fvisibility=default")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)

if(DISABLE_CURSES OR NOT CURSES_FOUND)
  set(HAVE_CURSES 0)
else(DISABLE_CURSES OR NOT CURSES_FOUND)
  set(HAVE_CURSES 1)
endif(DISABLE_CURSES OR NOT CURSES_FOUND)

if(DISABLE_GDRAGON OR NOT GTK_FOUND)
  set(BUILD_GDRAGON 0)
else(DISABLE_GDRAGON OR NOT GTK_FOUND)
  set(BUILD_GDRAGON 1)
endif(DISABLE_GDRAGON OR NOT GTK_FOUND)

if(DISABLE_KDRAGON OR NOT KDE4_FOUND)
  set(BUILD_KDRAGON 0)
else(DISABLE_KDRAGON OR NOT KDE4_FOUND)
  set(BUILD_KDRAGON 1)
endif(DISABLE_KDRAGON OR NOT KDE4_FOUND)

find_program(DOXYGEN_COMMAND doxygen)
if(DOXYGEN_COMMAND)
  configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in"
				 "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile"
				 IMMEDIATE @ONLY)
  add_custom_target(doc ALL ${DOXYGEN_COMMAND} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
						DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libdragonscript/src
						WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
  if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/html)
	install(DIRECTORY html DESTINATION ${CMAKE_DOC_PATH} PATTERN ".svn" EXCLUDE )
  endif(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/html)
  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/spec-en.pdf)
	file(GLOB PDF_FILES "${CMAKE_CURRENT_SOURCE_DIR}/doc/spec-*.pdf")
	install(FILES ${PDF_FILES} DESTINATION ${CMAKE_DOC_PATH}/pdf)
  endif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/spec-en.pdf)
endif(DOXYGEN_COMMAND)

find_program(PLATEX platex)
find_program(ELATEX latex)
find_program(MAKE_INDEX mendex)
find_program(DVIPDFMX dvipdfmx)
if(MAKE_DOC AND PLATEX AND ELATEX AND MAKE_INDEX AND DVIPDFMX)
  add_subdirectory(doc)
endif(MAKE_DOC AND PLATEX AND ELATEX AND MAKE_INDEX AND DVIPDFMX)

# This provides from CMAKE.
# find_program(TAR_COMMAND tar)
find_program(XZ_COMMAND  xz)
if(TAR_COMMAND AND XZ_COMMAND AND FIND_COMMAND)
  configure_file("${CMAKE_CURRENT_SOURCE_DIR}/make_dist.cmake.in"
			     "${CMAKE_CURRENT_BINARY_DIR}/make_dist.cmake" IMMEDIATE @ONLY)
  add_custom_target(dist ${CMAKE_COMMAND} "-P" "${CMAKE_CURRENT_BINARY_DIR}/make_dist.cmake"
					     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif(TAR_COMMAND AND XZ_COMMAND AND FIND_COMMAND)

# Do you think these searches success in Native Windows? 
message(STATUS "Looking for C++ Header Search module")
find_file(INCLUDE_CXX "CheckIncludeFileCXX.cmake" PATHS ${CMAKE_MODULE_PATH})
if(NOT INCLUDE_CXX)
  message(SEND_ERROR "Looking for C++ Header Search module - No!")
else(NOT INCLUDE_CXX)
  include("${INCLUDE_CXX}")
  
  ## STL
  CHECK_INCLUDE_FILE_CXX("vector"    HAVE_VECTOR)
  CHECK_INCLUDE_FILE_CXX("list"      HAVE_LIST)
  CHECK_INCLUDE_FILE_CXX("queue"     HAVE_QUEUE)
  CHECK_INCLUDE_FILE_CXX("map"       HAVE_MAP)
  CHECK_INCLUDE_FILE_CXX("stack"     HAVE_STACK)
  CHECK_INCLUDE_FILE_CXX("algorithm" HAVE_ALGORITHM)

  ## other cxx header.
  CHECK_INCLUDE_FILE_CXX("new"      HAVE_NEW)
  CHECK_INCLUDE_FILE_CXX("iostream" HAVE_IOSTREAM)
  CHECK_INCLUDE_FILE_CXX("string"   HAVE_STRING)

  ## c wrapper
  CHECK_INCLUDE_FILE_CXX("cstring" HAVE_CSTRING)
  CHECK_INCLUDE_FILE_CXX("cstdlib" HAVE_CSTDLIB)
  CHECK_INCLUDE_FILE_CXX("cstdio"  HAVE_CSTDIO)
  CHECK_INCLUDE_FILE_CXX("climits" HAVE_CLIMITS)
  CHECK_INCLUDE_FILE_CXX("cerrno"  HAVE_CERRNO)
endif(NOT INCLUDE_CXX)

message(STATUS "Checking Size of types")
include("CheckTypeSize.cmake")
CHECK_TYPE_SIZE("wchar_t"       SIZE_OF_WCHAR_T BUILTIN_TYPES_ONLY)
CHECK_TYPE_SIZE("int"           SIZE_OF_INT     BUILTIN_TYPES_ONLY)
CHECK_TYPE_SIZE("long long int" SIZE_OF_LLINT   BUILTIN_TYPES_ONLY)
CHECK_TYPE_SIZE("double"        SIZE_OF_DOUBLE  BUILTIN_TYPES_ONLY)
CHECK_TYPE_SIZE("long double"   SIZE_OF_LDOUBLE BUILTIN_TYPES_ONLY)

add_subdirectory(libdragonscript)
add_subdirectory(cdragon)

if(BUILD_GDRAGON)
  add_subdirectory(gdragon)
endif(BUILD_GDRAGON)

if(BUILD_KDRAGON)
  add_subdirectory(kdragon)
endif(BUILD_KDRAGON)

### Output investigation summary.
message(STATUS "----------------------------------------------------------------------")
message(STATUS "Hello. I'm an inspector dragon from dragons' world.")
message(STATUS "I'll make a report of this castle.")
if(CURSES_FOUND)
  message(STATUS "NCurses library is ... installed.")
  if(DISABLE_CURSES)
	message(STATUS "   But your offer is not to use NCurses.")
  else(DISABLE_CURSES)
	message(STATUS "   CDragon will can use powerful terminal controlling.")
  endif(DISABLE_CURSES)
else(CURSES_FOUND)
  message(STATUS "NCurses library is ... not installed.")
  message(STATUS "   I'll tell CDragon not to use NCurses.")
endif(CURSES_FOUND)
if(GTK_FOUND)
  message(STATUS "GIMP Tool Kit (gtk2) is ... installed.")
  if(DISABLE_GDRAGON)
	message(STATUS "   But your offer is not to call GDragons.")
  else(DISABLE_GDRAGON)
	message(STATUS "   GDragon (Gtk Dragon) will be called.")
  endif(DISABLE_GDRAGON)
else(GTK_FOUND)
  message(STATUS "GIMP Tool Kit (gtk2) is ... not installed.")
  message(STATUS "   I canceled to call GDragons.")
endif(GTK_FOUND)
if(KDE4_FOUND)
  message(STATUS "K Desktop Environment (KDE4) is ... installed.")
  if(DISABLE_KDRAGON)
	message(STATUS "   But your offer is not to call KDragons.")
  else(DISABLE_KDRAGON)
	message(STATUS "   KDragon (KDE Dragon) will be called.")
  endif(DISABLE_KDRAGON)
else(KDE4_FOUND)
  message(STATUS "K Desktop Environment (KDE4) is ... not installed.")
  message(STATUS "   I canceled to call KDragons.")
endif(KDE4_FOUND)
if(SIZE_OF_LLINT AND SIZE_OF_LLINT GREATER SIZE_OF_INT)
  message(STATUS "Size of int is ... ${SIZE_OF_INT}")
  message(STATUS "Size of long long int is ... ${SIZE_OF_LLINT}")
  message(STATUS "   You can use \"Big Integer\" as ${SIZE_OF_LLINT} bytes integer.")
else(SIZE_OF_LLINT AND SIZE_OF_LLINT GREATER SIZE_OF_INT)
  message(STATUS "Size of int is ... ${SIZE_OF_INT}")
  if(NOT SIZE_OF_LLINT)
	message(STATUS "Size of long long int is ... Ah, it can't use.")
  else(NOT SIZE_OF_LLINT)
	message(STATUS "Size of long long int is ... ${SIZE_OF_LLINT}")
  endif(NOT SIZE_OF_LLINT)
  message(STATUS "   You cannot use \"Big Integer\". It will be ${SIZE_OF_INT} bytes integer.")
endif(SIZE_OF_LLINT AND SIZE_OF_LLINT GREATER SIZE_OF_INT)
if(SIZE_OF_LDOUBLE AND SIZE_OF_LDOUBLE GREATER SIZE_OF_DOUBLE)
  message(STATUS "Size of double is ... ${SIZE_OF_DOUBLE}")
  message(STATUS "Size of long double is ... ${SIZE_OF_LDOUBLE}")
  message(STATUS "   You can use \"Big Real\" as ${SIZE_OF_LDOUBLE} bytes double.")
else(SIZE_OF_LDOUBLE AND SIZE_OF_LDOUBLE GREATER SIZE_OF_DOUBLE)
  message(STATUS "Size of double is ... ${SIZE_OF_DOUBLE}")
  if(NOT SIZE_OF_LDOUBLE)
	message(STATUS "Size of long double is ... Ah, it can't use.")
  else(NOT SIZE_OF_LDOUBLE)
	message(STATUS "Size of long double is ... ${SIZE_OF_LDOUBLE}")
  endif(NOT SIZE_OF_LDOUBLE)
  message(STATUS "   You cannot use \"Big Real\". It will be ${SIZE_OF_INT} bytes double.")
endif(SIZE_OF_LDOUBLE AND SIZE_OF_LDOUBLE GREATER SIZE_OF_DOUBLE)
if(SIZE_OF_WCHAR_T)
  message(STATUS "Size of wchar_t is ... ${SIZE_OF_WCHAR_T}")
  if(SIZE_OF_WCHAR_T EQUAL 2)
	message(STATUS "   We think wchar_t coding is \"UCS-2\".")
  elseif(SIZE_OF_WCHAR_T EQUAL 4)
	message(STATUS "   We think wchar_t coding is \"UCS-4\".")
  endif(SIZE_OF_WCHAR_T EQUAL 2)
else(SIZE_OF_WCHAR_T)
  message(SEND_ERROR "Size of wchar_t is ... Ah, it can't use.")
endif(SIZE_OF_WCHAR_T)
message(STATUS "I think you become a good king. Please enjoy ordering us!")
message(STATUS "But if you are disappointed about this configuration,")
message(STATUS "you can re-configure Dragon Script after installing other software.")
message(STATUS "----------------------------------------------------------------------")
### End reporting.

file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/config.h" "/* Generated by CMakeLists.txt */\n")

macro(WRITE_CONFIG_H_STR VAR_NAME COMMENT)
  file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h"
              "\n/* ${COMMENT} */\n")
  file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h" "#define ${VAR_NAME} \"${ARGV2}\"\n")
endmacro(WRITE_CONFIG_H_STR)

macro(WRITE_CONFIG_H_INT VAR_NAME COMMENT)
  file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h"
              "\n/* ${COMMENT} */\n")

  if("${ARGV2}" STREQUAL "")
	file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h" "/* ")
  endif("${ARGV2}" STREQUAL "")
  file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h" "#define ${VAR_NAME} (${ARGV2})")
  if("${ARGV2}" STREQUAL "")
	file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h" " */")
  endif("${ARGV2}" STREQUAL "")
  file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h" "\n")
endmacro(WRITE_CONFIG_H_INT)

macro(WRITE_CONFIG_H_TF VAR_NAME COMMENT)
  file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h"
			  "\n/* ${COMMENT} */\n")
  
  if("${ARGV2}" STREQUAL "" OR "${ARGV2}" STREQUAL "false" OR "${ARGV2}" STREQUAL "0")
	file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h" "#define ${VAR_NAME} (false)\n")
  else("${ARGV2}" STREQUAL "" OR "${ARGV2}" STREQUAL "false" OR "${ARGV2}" STREQUAL "0")
	file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/config.h" "#define ${VAR_NAME} (true)\n")
  endif("${ARGV2}" STREQUAL "" OR "${ARGV2}" STREQUAL "false" OR "${ARGV2}" STREQUAL "0")
endmacro(WRITE_CONFIG_H_TF)

WRITE_CONFIG_H_STR("DS_VERSION"      "Version of Dragon Script" "${PROJECT_STABLE_VERSION}")
WRITE_CONFIG_H_STR("MO_INSTALL_PATH" "Installation Path for Translation Files." "${CMAKE_INSTALL_PREFIX}/${MO_INSTALL_PATH}")
WRITE_CONFIG_H_STR("LIBDRAGONSCRIPT_DOMAIN_NAME" "Domain Name for libdragonscript." "${LIBDRAGONSCRIPT_DOMAIN_NAME}")
WRITE_CONFIG_H_STR("CDRAGON_DOMAIN_NAME" "Domain Name for cdragon." "${CDRAGON_DOMAIN_NAME}")
WRITE_CONFIG_H_STR("GDRAGON_DOMAIN_NAME" "Domain Name for gdragon." "${GDRAGON_DOMAIN_NAME}")
WRITE_CONFIG_H_STR("KDRAGON_DOMAIN_NAME" "Domain Name for kdragon." "${KDRAGON_DOMAIN_NAME}")
WRITE_CONFIG_H_TF( "HAVE_VECTOR"    "Header <vector>"           ${HAVE_VECTOR})
WRITE_CONFIG_H_TF( "HAVE_LIST"      "Header <list>"             ${HAVE_LIST})
WRITE_CONFIG_H_TF( "HAVE_QUEUE"     "Header <queue>"            ${HAVE_QUEUE})
WRITE_CONFIG_H_TF( "HAVE_MAP"       "Header <map>"              ${HAVE_MAP})
WRITE_CONFIG_H_TF( "HAVE_STACK"     "Header <stack>"            ${HAVE_STACK})
WRITE_CONFIG_H_TF( "HAVE_ALGORITHM" "Header <algorithm>"        ${HAVE_ALGORITHM})
WRITE_CONFIG_H_INT("INT_SIZE"     "Size of int"               ${SIZE_OF_INT})
WRITE_CONFIG_H_INT("LLINT_SIZE"   "Size of long long int"     ${SIZE_OF_LLINT})
WRITE_CONFIG_H_INT("DOUBLE_SIZE"  "Size of double"            ${SIZE_OF_DOUBLE})
WRITE_CONFIG_H_INT("LDOBULE_SIZE" "Size of long double"       ${SIZE_OF_LDOUBLE})
WRITE_CONFIG_H_INT("WCHAR_T_SIZE" "Size of wchar_t"           ${SIZE_OF_WCHAR_T})

### Rubbish thing.
if(NOT NOT)
  set(NOT " NOT ")
endif(NOT NOT)
if(NOT A_GOOD)
  set(A_GOOD "a good")
endif(NOT A_GOOD)

set(FIRST_MESSAGE  "Hello,")
set(SECOND_MESSAGE "I'm a dragon who lives in your castle.")
set(THIRD_MESSAGE  "Nice to meet you.")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/INSPIRATION.in"
			   "${CMAKE_CURRENT_BINARY_DIR}/INSPIRATION"
			   IMMEDIATE @ONLY)
